/**
 * Copyright (C), 2015-2019, XXX有限公司
 * FileName: WebSecurityConfig
 * Author:   zhouheng
 * Date:     2019/3/30 21:51
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.onesquare.uaa.config;

import com.onesquare.uaa.service.UserServiceDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 〈一句话功能简述〉<br> 
 * 〈〉
 *
 * @author zhouheng
 * @create 2019/3/30
 * @since 1.0.0
 */

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    UserServiceDetail userServiceDetail;

    // AuthenticationManagerBuilder 配置了如何验证用户信息
    // 应用的每
    // 个请求都需要验证 阻止了csrf攻击
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userServiceDetail)
                .passwordEncoder(new BCryptPasswordEncoder());
    }

    // HttpSecurity 配置了是否所有用户都需要验证
    // 配置了 哪些资源需要验证 哪些资源不需要验证
    // 配置了基于表单的身份验证
    //CSRF:因为不再依赖于Cookie，所以你就不需要考虑对CSRF（跨站请求伪造）的防范。
    //authorizeRequests所有security全注解配置实现的开端，表示开始说明需要的权限。
    //需要的权限分两部分，第一部分是拦截的路径，第二部分访问该路径需要的权限。
    //antMatchers表示拦截什么路径，permitAll任何权限都可以访问，直接放行所有。
    //anyRequest()任何的请求，authenticated认证后才能访问
    //.and().csrf().disable();固定写法，表示使csrf拦截失效。
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .exceptionHandling()
                .authenticationEntryPoint(new AuthenticationEntryPoint() {
                    @Override
                    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException authException) throws IOException, ServletException {
                        if(isAjaxRequest(httpServletRequest)){
                            httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED,authException.getMessage());
                        }else{
                            httpServletResponse.sendRedirect("/login");
                        }
//                        httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
                    }

                    public boolean isAjaxRequest(HttpServletRequest request) {
                        String ajaxFlag = request.getHeader("X-Requested-With");
                        return ajaxFlag != null && "XMLHttpRequest".equals(ajaxFlag);
                    }
                }).and()
                .authorizeRequests()
                .antMatchers("/**").authenticated()
                .and()
                .httpBasic();
    }

    // 开启密码验证
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}